home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 October / EnigmA AMIGA RUN 01 (1995)(G.R. Edizioni)(IT)[!][issue 1995-10][Aminet 7].iso / Aminet / comm / tcp / wu_ftpd_37_21.lha / wu-ftpd / src / hostacc.c < prev    next >
C/C++ Source or Header  |  1994-06-02  |  12KB  |  333 lines

  1. /*
  2.  *      @(#) hostacc.c  -       Implementation of host access for the
  3.  *                              experimental FTP daemon developed at
  4.  *                              Washington University.
  5.  *
  6.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  7.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  8.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  9.  *
  10.  * AUTHOR
  11.  *      Bart Muijzer    <bartm@cv.ruu.nl>
  12.  *
  13.  * HISTORY
  14.  *      930316  BM      Created
  15.  *      930317  BM      Converted to local naming convention;
  16.  *                      added rhost_ok(), cleanup code in enghacc()
  17.  *      930318  BM      Ported to BSD; fixed memory leaks
  18.  *      930322  BM      Changed algorithm: not in configfile =  allow
  19.  *                                         in configfile and match = allow|deny
  20.  *                                         in configfile and no match = deny
  21.  */
  22.  
  23. #include "config.h"
  24.  
  25. #ifdef  HOST_ACCESS
  26.  
  27. #include "hostacc.h"
  28.  
  29. static  char    linbuf[MAXLEN];  /* Buffer to hold one line of config-file  */
  30. static  char    unibuf[MAXLEN];  /* Buffer to hold unified line             */
  31. static  hacc_t  ha_arr[MAXLIN];  /* Array with host access information      */
  32.  
  33. static  FILE    *ptFp;           /* FILE * into host access config file     */
  34. static  int     iHaInd = 0;      /* Index in ha_arr                         */
  35. static  int     iHaSize;         /* Will hold actual #elems in ha_arr       */
  36. static  int     iFirstTim = 1;   /* Used by gethacc() to see if index in    */
  37.                                  /* ha_arr needs to be reset                */
  38.  
  39. /* ------------------------------------------------------------------------ *\
  40.  * FUNCTION  : rhost_ok                                                     *
  41.  * PURPOSE   : Check if a host is allowed to make a connection              *
  42.  * ARGUMENTS : Remote user name, remote host name, remote host address      *
  43.  * RETURNS   : 1 if host is granted access, 0 if not                        *
  44. \* ------------------------------------------------------------------------ */
  45.  
  46. int     rhost_ok(pcRuser, pcRhost, pcRaddr)
  47. char    *pcRuser,
  48.         *pcRhost,
  49.         *pcRaddr;
  50. {
  51.         hacc_t  *ptHtmp;
  52.         char    *pcHost;
  53.         int     iInd, iLineMatch = 0, iUserSeen = 0;
  54.  
  55.         switch(sethacc()){
  56.         case 1:
  57.                 /* no hostaccess file; disable mechanism */
  58.                 return(1);
  59.                 break;
  60.         case -1:
  61.                 syslog(LOG_INFO, "rhost_ok: sethacc failed");
  62.                 return(0);
  63.                 break;
  64.         default:
  65.                 break;
  66.         }
  67.  
  68.         while (((ptHtmp = gethacc()) != (hacc_t *)NULL) && !iLineMatch)
  69.         {
  70.                 if ( (strcasecmp(pcRuser, ptHtmp->ha_login)) &&
  71.                       strcmp(ptHtmp->ha_login, "*") != NULL)
  72.                         /* wrong user, check rest of file */
  73.                         continue;
  74.  
  75.                 /*
  76.                  * We have seen a line regarding the current user.
  77.                  * Remember this.
  78.                  */
  79.                 iUserSeen = 1;
  80.  
  81.                 for(iInd=0, pcHost=ptHtmp->ha_hosts[0];
  82.                     ((pcHost != NULL) && !iLineMatch);
  83.                     pcHost=ptHtmp->ha_hosts[++iInd])
  84.                 {
  85.                         if (isdigit(*pcHost))
  86.                         {
  87.                                 iLineMatch = fnmatch(pcHost, pcRaddr, NULL);
  88.                         }
  89.                         else
  90.                         {
  91.                                 iLineMatch = fnmatch(pcHost, pcRhost, NULL);
  92.                         }
  93.                         if (iLineMatch)
  94.                         {
  95.                                 iLineMatch = (ptHtmp->ha_type == ALLOW) ? 1 : 0;
  96.                                 goto match;
  97.                         }
  98.                 }
  99.         }
  100.  
  101. match:
  102.         /*
  103.          * At this point, iUserSeen == 1 if we've seen lines regarding
  104.          * the current user, and 0 otherwise. If we reached the end of
  105.          * the config file without a match we allow. Else, we allow or
  106.          * deny according to the rule found.
  107.          */
  108.  
  109.         if (endhacc())
  110.         {
  111.                 syslog(LOG_INFO, "rhost_ok: endhacc failed");
  112.                 return(0);
  113.         }
  114.  
  115.         if (iUserSeen)
  116.                 return(ptHtmp == NULL) ? 0 : iLineMatch;
  117.         else
  118.                 /* Nothing at all about user in configfile, allow */
  119.                 return(1);
  120. }
  121.  
  122. /* ------------------------------------------------------------------------ *\
  123.  * FUNCTION  : sethacc                                                      *
  124.  * PURPOSE   : Initialize data structures for host access                   *
  125.  * ARGUMENTS : None                                                         *
  126.  * RETURNS   : -1 on failure, 1 if host access file doesn't exist,          *
  127.  *             0 otherwise                                                  *
  128. \* ------------------------------------------------------------------------ */
  129.  
  130. static  int     sethacc()
  131. {
  132.         int     iHaHind = 0;                    /* Index in list of hosts   */
  133.         char    *pcBegin, *pcEnd, *pcColon;
  134.         char    *pcTmp1, *pcTmp2;
  135.  
  136.         /* Open config file */
  137.         if ((ptFp = fopen(_PATH_FTPHOSTS, "r")) == NULL)
  138.         {
  139.                 if (errno == ENOENT)
  140.                         return(1);
  141.                 else {
  142.                 fatal("Can't open host access file");
  143.                 return (-1);
  144.                 }
  145.         }
  146.  
  147.         while (fgets(linbuf, MAXLEN, ptFp) != NULL)
  148.         {
  149.                 iHaHind = 0;
  150.  
  151.                 /* Find first non-whitespace character */
  152.                 for (pcBegin=linbuf;
  153.                      ((*pcBegin == '\t') || (*pcBegin == ' '));
  154.                      pcBegin++)
  155.                         ;
  156.                 
  157.                 /* Get rid of comments */
  158.                 if ((pcEnd = strchr(linbuf, '#')) != NULL)
  159.                         *pcEnd = '\0';
  160.                 
  161.  
  162.                 /* Skip empty lines */
  163.                 if ((pcBegin == pcEnd) || (*pcBegin == '\n'))
  164.                         continue;
  165.                 
  166.                 /* Substitute all whitespace by a single ":" so we can
  167.                  * easily break on words later on. The easiest way is 
  168.                  * to copy the result into a temporary buffer (called
  169.                  * the "unified buffer" because it will store a line in 
  170.                  * the same format, regardless of the format the original
  171.                  * line was in).
  172.                  * The result will look like: "allow:name:host:host:host"
  173.                  */
  174.                 for (pcTmp1=pcBegin, pcTmp2=unibuf; *pcTmp1; pcTmp1++)
  175.                 {
  176.                         if (*pcTmp1 != '\t' && *pcTmp1 != ' ' && *pcTmp1 != '\n')
  177.                                 *pcTmp2++ = *pcTmp1;
  178.                         else
  179.                                 /* whitespace */
  180.                                 if (*(pcTmp2-1) == ':')
  181.                                         continue;
  182.                                 else
  183.                                         *pcTmp2++ = ':';
  184.                 }
  185.  
  186.                 /* Throw away trailing whitespace, now indicated by
  187.                  * the last character of the unified buffer being a 
  188.                  * colon. Remember where the news string ends.
  189.                  */
  190.                 pcEnd = (*(pcTmp2 - 1) == ':') ? (pcTmp2 - 1) : pcTmp2;
  191.                 *pcEnd = '\0';          /* Terminate new string */
  192.                                 
  193.                 /* Store what's left of the line into the
  194.                  * hacc_t structure. First the access type,
  195.                  * then the loginname, and finally a list of
  196.                  * hosts to which all this applies.
  197.                  */
  198.                 pcBegin = unibuf;
  199.                 if (!strncmp(pcBegin, "deny", 4))
  200.                 {
  201.                         ha_arr[iHaInd].ha_type = DENY;
  202.                         pcBegin += 5;
  203.                 } else 
  204.                         if (!strncmp(pcBegin, "allow", 5))
  205.                         {
  206.                                 ha_arr[iHaInd].ha_type = ALLOW;
  207.                                 pcBegin += 6;
  208.                         }
  209.                         else {
  210.                                 fatal("Format error in host access file");
  211.                                 return(-1);
  212.                         }
  213.  
  214.                 if((pcColon = strchr(pcBegin, ':')) != NULL)
  215.                         ha_arr[iHaInd].ha_login =
  216.                                 strnsav(pcBegin, (pcColon-pcBegin));
  217.                 else
  218.                 {
  219.                         fatal("Format error in host access file");
  220.                         return(-1);
  221.                 }
  222.  
  223.                 pcBegin = pcColon+1;
  224.                 while ((pcColon = strchr(pcBegin, ':')) != NULL)
  225.                 {
  226.                         ha_arr[iHaInd].ha_hosts[iHaHind++] =
  227.                                 strnsav(pcBegin, (pcColon-pcBegin));
  228.                         pcBegin = pcColon+1;
  229.                         if (iHaHind >= MAXHST)
  230.                         {
  231.                                 fatal("Line too long");
  232.                                 return(-1);
  233.                         }
  234.                 }
  235.                 ha_arr[iHaInd].ha_hosts[iHaHind++] =
  236.                                 strnsav(pcBegin, (pcEnd-pcBegin));
  237.                 ha_arr[iHaInd].ha_hosts[iHaHind] = NULL;
  238.  
  239.                 /*
  240.                  * Check if we need to expand the array with
  241.                  * host access information
  242.                  */
  243.                 if (++iHaInd > MAXLIN)
  244.                 {
  245.                         fatal("Config file too big!!");
  246.                         return(-1);
  247.                 }
  248.         }
  249.         iHaSize = iHaInd;               /* Record current size of ha_arr */
  250.         return ((feof(ptFp)) ? 0 : -1);
  251. }
  252.  
  253. /* ------------------------------------------------------------------------ *\
  254.  * FUNCTION  : gethacc                                                      *
  255.  * PURPOSE   : return pointer to the next host_access structure             *
  256.  * ARGUMENTS : None                                                         *
  257.  * RETURNS   : NULL on failure, pointervalue otherwise                      *
  258. \* ------------------------------------------------------------------------ */
  259.  
  260. static  hacc_t  *gethacc()
  261. {
  262.         static  int     iHaInd;
  263.         hacc_t  *ptTmp;
  264.  
  265.         if ((ptTmp = (hacc_t *)malloc(sizeof(hacc_t))) == NULL)
  266.                 return(NULL);
  267.  
  268.         if (iFirstTim)
  269.         {
  270.                 iFirstTim = 0;
  271.                 iHaInd = 0;
  272.         }
  273.         if (iHaInd >= iHaSize)
  274.                 return ((hacc_t *)NULL);
  275.         else {
  276. #ifdef USG
  277.                 memmove(ptTmp, &(ha_arr[iHaInd]), sizeof(hacc_t));
  278. #else
  279.                 bcopy(&(ha_arr[iHaInd]), ptTmp, sizeof(hacc_t));
  280. #endif
  281.                 iHaInd++;
  282.                 return(ptTmp);
  283.         }
  284. }
  285.  
  286. /* ------------------------------------------------------------------------ *\
  287.  * FUNCTION  : endhacc                                                      *
  288.  * PURPOSE   : Free allocated data structures for host access               *
  289.  * ARGUMENTS : None                                                         *
  290.  * RETURNS   : -1 on failure, 0 otherwise                                   *
  291. \* ------------------------------------------------------------------------ */
  292.  
  293. static  int     endhacc()
  294. {
  295.         int     iInd;
  296.         hacc_t  *ptHtmp;
  297.  
  298.         for(iInd=0, ptHtmp = ha_arr;
  299.             (ptHtmp->ha_hosts[iInd]);
  300.             iInd++)
  301.         {
  302.                 free(ptHtmp->ha_login);
  303.                 free(ptHtmp->ha_hosts[iInd]);
  304.         }
  305.  
  306.         if (fclose(ptFp))
  307.                 return (-1);
  308.         return (0);
  309. }
  310.  
  311. /* ------------------------------------------------------------------------ */
  312.  
  313. static  void    fatal(pcMsg)
  314. char    *pcMsg;
  315. {
  316.         syslog(LOG_INFO, "host_access: %s", pcMsg);
  317. }
  318.  
  319. static  char    *strnsav(pcStr,iLen)
  320. char    *pcStr;
  321. int     iLen;
  322. {
  323.         char    *pcBuf;
  324.  
  325.         if ((pcBuf = (char *)malloc(iLen+1)) == NULL)
  326.                 return(NULL);
  327.         strncpy(pcBuf,pcStr,iLen);
  328.         pcBuf[iLen] = '\0';
  329.         return(pcBuf);
  330. }
  331.  
  332. #endif  /* HOST_ACCESS */
  333.